package org.aldar.bquest.screens;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import org.aldar.bquest.entity.LoggedScene;
import org.aldar.bquest.entity.effect.ParticleEmitter;
import org.aldar.bquest.entity.effect.ParticleUtil;
import org.aldar.bquest.logic.controller.level.LevelAreaDef;
import org.aldar.bquest.logic.controller.level.LevelDef;
import org.aldar.bquest.logic.controller.level.LevelDefinition;
import org.aldar.bquest.profile.GameProfile;
import org.aldar.bquest.sound.GameSound;
import org.aldar.bquest.util.CustomButtonSprite;
import org.aldar.bquest.util.Logger;
import org.aldar.bquest.util.SQLiteHelper;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.handler.IUpdateHandler;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.Entity;
import org.andengine.entity.IEntity;
import org.andengine.entity.modifier.*;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.CameraScene;
import org.andengine.entity.scene.IOnSceneTouchListener;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.entity.text.TextOptions;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.font.Font;
import org.andengine.opengl.font.FontFactory;
import org.andengine.opengl.texture.Texture;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.ITiledTextureRegion;
import org.andengine.util.adt.align.HorizontalAlign;
import org.andengine.util.modifier.IModifier;

import javax.microedition.khronos.opengles.GL10;
import java.io.IOException;
import java.util.*;

import static org.aldar.bquest.util.SpriteUtil.revealEntityAndChildren;

/**
 * User: Daria
 * Date: 1/12/14 8:34 PM
 */
public class LevelMapScreen extends LoggedSimpleBaseGameActivity implements IOnSceneTouchListener {

    private static final Logger LOG = new Logger(LevelMapScreen.class);

    protected CameraScene mLoadScreen;
    protected List<Texture> mAllTextures = new LinkedList<Texture>();
    protected int TextureCount;
    protected long loadStart;
    protected long loadFinish;
    protected long prevLoaded;
    protected long textureLoadStarted;

    private boolean dragInAction = false;
    private Runnable backButtonAction = null;
    float touchX;
    float touchY;

    private static final int CAMERA_WIDTH = 480;
    private static final int CAMERA_HEIGHT = 800;

    private static final int MAP_BORDER_BOTTOM = 0;
    private static final int MAP_BORDER_TOP = 0;        //100;

    private static final int MAP_WIDTH = 480;
    private static final int MAP_HEIGHT = 2070;

    private static final Map<String, float[]> finishedLevelDots = new HashMap<String, float[]>();


    public static Integer areaToHighlightAtStart;
    public static Integer levelToHighlightAtStart;


    private Entity bgLayer;

    protected Camera mCamera;

    protected Scene scene;
    private SQLiteHelper mSQLiteHelper = new SQLiteHelper(this);

    protected ITextureRegion bgTextureRegion;
    private ITextureRegion frameTextureRegion;
    private Entity levelMapImage;
    private Entity popupLayer;

    private CustomButtonSprite buttonStartGame;
    private CustomButtonSprite buttonUnlockArea;
    private Entity levelHighlight;
    private List<Entity> currentLevelIcons;
    private List<Entity> levelHighlights;
    private Font fontTrebuchetBoldGold;
    private ITextureRegion unlockPopupTextureRegion;
    private ITextureRegion areaReqGreenGreenRegion;
    private ITextureRegion areaReqRedGreenRegion;
    private ITextureRegion areaReqGreenRedRegion;
    private ITextureRegion areaReqRedRedRegion;
    private Entity unlockPopupContent;
    private Entity closeButton;

    private boolean isPopupShown = false;
    private ITiledTextureRegion buttonClosedPressedTextureRegion;
    private ITiledTextureRegion buttonUnlockTextureRegion;
    private Font fontTrebuchetBoldGoldSmall;
    private Text totalPointsTopText;
    private Text totalFameTopText;
    private ITextureRegion[] levelNumberIcon;
    private ITextureRegion levelIconDone;
    private ITextureRegion levelIconLocked;
    private ITextureRegion levelIconReady;
    private ITextureRegion levelSelectedFrame;
    private ITextureRegion selectLevelPopupTextureRegion;
    private ITiledTextureRegion buttonPlayTextureRegion;
    private ITextureRegion fameEmptyIconRegion;
    private ITextureRegion fameGoldIconRegion;
    private ITextureRegion levelIconDoneV;
    private Map<Integer, ITextureRegion> setIconsAvailable;
    private Map<Integer, ITextureRegion> setIconsLocked;
    private Map<Integer, ITextureRegion> setPopupIllos;
    private Map<Integer, ITextureRegion> roadPartsOpened;
    private Map<Integer, ITextureRegion> roadPartsLocked;
    private Sprite levelMapPart1;
    final Map<Integer, Entity> areaList = new HashMap<Integer, Entity>();
    final Map<Integer, Entity> roadList = new HashMap<Integer, Entity>();
    private ITextureRegion goldParticleRegion;
    private Entity roadLayer;
    private List<String> mAllTextureNames = new LinkedList<String>();
    private ITiledTextureRegion levelIconJewels;
    private ITiledTextureRegion levelNumbers;
    private ITextureRegion loadingScreenBgTextureRegion;
    private ITextureRegion loadingScreenBarFrameTextureRegion;
    private ITextureRegion loadingScreenBarProgressTextureRegion;
    private Sprite progressBar;
    private ITextureRegion blueParticleRegion;
    private ITextureRegion levelCompleteDot;


    protected void createLoadScreen() {
        mLoadScreen = new CameraScene(mCamera);
        mLoadScreen.setBackgroundEnabled(true);
        Sprite bg = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2, loadingScreenBgTextureRegion, getVertexBufferObjectManager());
        Sprite barFrame = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 - 17, loadingScreenBarFrameTextureRegion, getVertexBufferObjectManager());
        progressBar = new Sprite(CAMERA_WIDTH / 2 - loadingScreenBarProgressTextureRegion.getWidth() / 2, CAMERA_HEIGHT / 2 - 17, loadingScreenBarProgressTextureRegion, getVertexBufferObjectManager());
        progressBar.setAnchorCenter(0, 0.5f);
        progressBar.setScaleX(0);
        mLoadScreen.attachChild(bg);
        mLoadScreen.attachChild(progressBar);
        mLoadScreen.attachChild(barFrame);
        scene.setChildScene(mLoadScreen, false, true, true);
        scene.setChildrenIgnoreUpdate(true);
    }

    public void loadTextures(final boolean pResume) {
        TextureCount = -1;
        Log.d("Echo", "Begin Load - T: " + TextureCount + " - pResume: " + pResume);
        loadStart = new Date().getTime();
        mLoadScreen.registerUpdateHandler(new IUpdateHandler() {
            @Override
            public void onUpdate(float pSecondsElapsed) {
                TextureCount++;
                if (prevLoaded != 0) {
                    Log.d("Echo", "Prev load: " + (new Date().getTime() - prevLoaded) + " ms.");
                }
                prevLoaded = new Date().getTime();
                if (TextureCount < mAllTextures.size()) {
                    mEngine.getTextureManager().loadTexture(mAllTextures.get(TextureCount));
                    Log.d("Echo", "Loaded texture: " + (TextureCount + 1) + " of " + mAllTextures.size() + ". filename: " + mAllTextureNames.get(TextureCount));
                    for (int i = 0; i < 7; i++) {
                        TextureCount++;
                        if (TextureCount < mAllTextures.size()) {
                            mEngine.getTextureManager().loadTexture(mAllTextures.get(TextureCount));
                            Log.d("Echo", "Loaded texture: " + (TextureCount + 1) + " of " + mAllTextures.size() + ". filename: " + mAllTextureNames.get(TextureCount));
                        }
                    }
                    if (progressBar.getEntityModifierCount() == 0) {
                        progressBar.registerEntityModifier(new ScaleModifier(0.3f, progressBar.getScaleX(), Math.min(((float) TextureCount) / mAllTextures.size(), 1f), 1, 1));
                    }
                    //progressBar.setScaleX(Math.min(((float) TextureCount) / mAllTextures.size(), 1f));

                } else {
                    mLoadScreen.unregisterUpdateHandler(this);
                    mEngine.getFontManager().onReload();
                    loadFinish = new Date().getTime();
                    LOG.i("Echo Loaded textures in " + (loadFinish - loadStart) + " ms.");
                    if (pResume) {
                        Log.d("Echo", "Textures Loaded, Resuming...");
                        scene.setChildrenIgnoreUpdate(false);
                        scene.back();
                    } else {
                        Log.d("Echo", "Textures Loaded, proceeding to MainMenu");
                        // set scene to main menu or however your project is setup
                        scene.clearChildScene();
                        scene.setChildrenIgnoreUpdate(false);
                    }
                }
            }

            @Override
            public void reset() {
            }
        });
    }


    @Override
    public Scene onMyCreateScene() {
        this.scene = new LoggedScene(this);

        this.init();
        GameSound sound = new GameSound(this, this.mEngine.getSoundManager(), mEngine.getMusicManager());
        sound.initSound();
        GameSound.setCurrentInstance(sound);
        SQLiteHelper.setCurrentInstance(mSQLiteHelper);

        Log.i("levelmapscreen", "values at start: " + areaToHighlightAtStart + "  " + levelToHighlightAtStart);
        //do not shoe any popups on opening map screen. the current set will be centered if areaToHighlightAtStart != null
        /*
        if (areaToHighlightAtStart != null) {
            int lastUnlockedAreaIndex = GameProfile.getLastUnlockedAreaIndex(mSQLiteHelper);
            if (lastUnlockedAreaIndex < areaToHighlightAtStart) {
                showUnlockAreaPopup(areaToHighlightAtStart);
            } else {
                showLevelAreaPopup(areaToHighlightAtStart, levelToHighlightAtStart);
            }
        }
        //reset values
        LevelMapScreen.levelToHighlightAtStart = null;
        LevelMapScreen.areaToHighlightAtStart = null;
        */
        scene.registerUpdateHandler(new IUpdateHandler() {
            @Override
            public void onUpdate(float pSecondsElapsed) {
                if (loadingScreenBgTextureRegion.getTexture().isLoadedToHardware()) {
                    scene.unregisterUpdateHandler(this);
                    createLoadScreen();
                    loadTextures(false);
                    // boolean true if resuming - more on this later
                }
            }

            @Override
            public void reset() {
            }
        });
        return scene;
    }

    @Override
    public void onResume() {
        if (scene != null) {
            TextureCount = 0;
            scene.registerUpdateHandler(new IUpdateHandler() {
                @Override
                public void onUpdate(float pSecondsElapsed) {
                    mEngine.getTextureManager().unloadTexture(loadingScreenBgTextureRegion.getTexture());
                    if (!loadingScreenBgTextureRegion.getTexture().isLoadedToHardware()) {
                        scene.unregisterUpdateHandler(this);
                        scene.registerUpdateHandler(new IUpdateHandler() {
                            @Override
                            public void onUpdate(float pSecondsElapsed) {
                                mEngine.getTextureManager().loadTexture(loadingScreenBgTextureRegion.getTexture());
                                if (loadingScreenBgTextureRegion.getTexture().isLoadedToHardware()) {
                                    scene.unregisterUpdateHandler(this);
                                    scene.setChildScene(mLoadScreen, false, true, true);
                                    scene.setChildrenIgnoreUpdate(true);
                                    if (progressBar != null) {
                                        progressBar.setScaleX(0);
                                    }
                                    mLoadScreen.registerUpdateHandler(new IUpdateHandler() {
                                        @Override
                                        public void onUpdate(float pSecondsElapsed) {
                                            if (TextureCount < mAllTextures.size()) {
                                                Log.d("Echo", "UnLoading texture: " + (TextureCount + 1) + " of " + mAllTextures.size());
                                                mEngine.getTextureManager().unloadTexture(mAllTextures.get(TextureCount));
                                                for (int i = 0; i < 20; i++) {
                                                    TextureCount++;
                                                    if (TextureCount < mAllTextures.size()) {
                                                        mEngine.getTextureManager().unloadTexture(mAllTextures.get(TextureCount));
                                                        Log.d("Echo", "UnLoaded texture: " + (TextureCount + 1) + " of " + mAllTextures.size());
                                                    }
                                                }
                                            } else {
                                                if (!mAllTextures.get(mAllTextures.size() - 1).isLoadedToHardware()) {
                                                    mLoadScreen.unregisterUpdateHandler(this);
                                                    Log.d("Echo", "UnLoading complete");
                                                    loadTextures(true);
                                                } else {
                                                    TextureCount++;
                                                    Log.d("Echo", "UnLoading Next texture: " + (TextureCount + 1));
                                                }
                                            }
                                        }

                                        @Override
                                        public void reset() {
                                        }
                                    });
                                }
                            }

                            @Override
                            public void reset() {
                            }
                        });
                    }
                }

                @Override
                public void reset() {
                }
            });
        } else {
            Log.d("Echo", "ON RESUME");
        }
        super.onResume();
    }

    protected void onMyCreateResources() throws IOException {


        BitmapTextureAtlas t = new BitmapTextureAtlas(this.getTextureManager(), 480, 800, TextureOptions.DEFAULT);
        loadingScreenBgTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(t, this, "gfx/common/loading_screen_bg.png", 0, 0);
        t.load();
        t = new BitmapTextureAtlas(this.getTextureManager(), 280, 27, TextureOptions.DEFAULT);
        loadingScreenBarFrameTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(t, this, "gfx/common/loadingbar_frame.png", 0, 0);
        t.load();
        t = new BitmapTextureAtlas(this.getTextureManager(), 270, 21, TextureOptions.DEFAULT);
        loadingScreenBarProgressTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(t, this, "gfx/common/loadingbar_progress.png", 0, 0);
        t.load();

        loadResources();
    }

    protected void loadResources() throws IOException {

        setIconsAvailable = new HashMap<Integer, ITextureRegion>();
        setIconsAvailable.put(0, load("gfx/levelmap/seticons/set_01.png", 166, 223, this));
        setIconsAvailable.put(1, load("gfx/levelmap/seticons/set_02.png", 166, 223, this));
        setIconsAvailable.put(2, load("gfx/levelmap/seticons/set_03.png", 166, 223, this));
        setIconsAvailable.put(3, load("gfx/levelmap/seticons/set_04.png", 166, 223, this));
        setIconsAvailable.put(4, load("gfx/levelmap/seticons/set_05.png", 166, 223, this));
        setIconsAvailable.put(5, load("gfx/levelmap/seticons/set_06.png", 166, 223, this));
        setIconsAvailable.put(6, load("gfx/levelmap/seticons/set_07.png", 166, 223, this));
        setIconsAvailable.put(7, load("gfx/levelmap/seticons/set_08.png", 166, 223, this));

        setIconsLocked = new HashMap<Integer, ITextureRegion>();
        setIconsLocked.put(1, load("gfx/levelmap/seticons/set_02_locked.png", 166, 223, this));
        setIconsLocked.put(2, load("gfx/levelmap/seticons/set_03_locked.png", 166, 223, this));
        setIconsLocked.put(3, load("gfx/levelmap/seticons/set_04_locked.png", 166, 223, this));
        setIconsLocked.put(4, load("gfx/levelmap/seticons/set_05_locked.png", 166, 223, this));
        setIconsLocked.put(5, load("gfx/levelmap/seticons/set_06_locked.png", 166, 223, this));
        setIconsLocked.put(6, load("gfx/levelmap/seticons/set_07_locked.png", 166, 223, this));
        setIconsLocked.put(7, load("gfx/levelmap/seticons/set_08_locked.png", 166, 223, this));

        setPopupIllos = new HashMap<Integer, ITextureRegion>();
        setPopupIllos.put(0, load("gfx/levelmap/seticons/illo_set01.png", 176, 218, this));
        setPopupIllos.put(1, load("gfx/levelmap/seticons/illo_set02.png", 176, 218, this));
        setPopupIllos.put(2, load("gfx/levelmap/seticons/illo_set03.png", 176, 218, this));
        setPopupIllos.put(3, load("gfx/levelmap/seticons/illo_set04.png", 176, 218, this));
        setPopupIllos.put(4, load("gfx/levelmap/seticons/illo_set05.png", 176, 218, this));
        setPopupIllos.put(5, load("gfx/levelmap/seticons/illo_set06.png", 176, 218, this));
        setPopupIllos.put(6, load("gfx/levelmap/seticons/illo_set07.png", 176, 218, this));
        setPopupIllos.put(7, load("gfx/levelmap/seticons/illo_set08.png", 176, 218, this));


        roadPartsOpened = new HashMap<Integer, ITextureRegion>();
        roadPartsLocked = new HashMap<Integer, ITextureRegion>();
        for (int i = 0; i < 9; i++) {
            roadPartsOpened.put(i + 1, load("gfx/levelmap/roadparts/road_0" + (i + 1) + ".png", 1000, 1000, this, false));
            roadPartsLocked.put(i + 1, load("gfx/levelmap/roadparts/road_0" + (i + 1) + "_locked.png", 1000, 1000, this, false));
        }

        //bgTextureRegion = load("gfx/levelmap/map-3.png", 1000, 1000, this);
        bgTextureRegion = load("gfx/levelmap/map.jpg", MAP_WIDTH, MAP_HEIGHT, this);
        goldParticleRegion = load("gfx/particle_gold.png", 25, 25, this);
        blueParticleRegion = load("gfx/particle.png", 25, 25, this);

        unlockPopupTextureRegion = load("gfx/levelmap/popup_unlock_bg.png", 480, 800, this);

        areaReqGreenGreenRegion = load("gfx/levelmap/requirements_green_green.png", 310, 83, this);
        areaReqRedGreenRegion = load("gfx/levelmap/requirements_red_green.png", 310, 83, this);
        areaReqGreenRedRegion = load("gfx/levelmap/requirements_green_red.png", 310, 83, this);
        areaReqRedRedRegion = load("gfx/levelmap/requirements_red_red.png", 310, 83, this);

        buttonClosedPressedTextureRegion = loadTiled("gfx/levelfinished/btn_close_pressed.png", 110, 55, 2, 1, this);
        buttonUnlockTextureRegion = loadTiled("gfx/levelmap/btn_unlock.png", 310, 65, 2, 1, this);
        levelNumberIcon = new ITextureRegion[6];
        for (int i = 0; i < 6; i++) {
            levelNumberIcon[i] = load("gfx/levelmap/level_" + (i + 1) + ".png", 100, 106, this);
        }
        levelIconDone = load("gfx/levelmap/level_done.png", 100, 106, this);
        levelIconDoneV = load("gfx/levelmap/level_done_v.png", 100, 106, this);
        levelIconLocked = load("gfx/levelmap/level_locked.png", 100, 106, this);
        levelIconReady = load("gfx/levelmap/level_ready.png", 100, 106, this);
        levelSelectedFrame = load("gfx/levelmap/level_selected.png", 116, 116, this);
        selectLevelPopupTextureRegion = load("gfx/levelmap/popup_level_select_bg.png", 480, 800, this);
        buttonPlayTextureRegion = loadTiled("gfx/levelmap/btn_play.png", 310, 65, 2, 1, this);
        fameEmptyIconRegion = load("gfx/levelmap/fame_0.png", 18, 34, this);
        fameGoldIconRegion = load("gfx/levelmap/fame_1.png", 18, 34, this);

        levelCompleteDot = load("gfx/levelmap/lvl_complete.png", 20, 20, this);

        frameTextureRegion = load("gfx/levelmap/map_frame.png", 480, 800, this);
        levelIconJewels = loadTiled("gfx/levelmap/level_btn.png", 464, 232, 4, 2, this);
        levelNumbers = loadTiled("gfx/levelmap/numbers.png", 696, 232, 6, 2, this);

        BitmapTextureAtlas fontTrebuchetTexture = new BitmapTextureAtlas(getTextureManager(), 256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
        BitmapTextureAtlas fontTrebuchetTexture2 = new BitmapTextureAtlas(getTextureManager(), 256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
        this.fontTrebuchetBoldGold = FontFactory.createFromAsset(getFontManager(), fontTrebuchetTexture, getAssets(), "fonts/Trebuchet_MS_bold.ttf", 25, true, Color.rgb(243, 180, 58));
        this.fontTrebuchetBoldGoldSmall = FontFactory.createFromAsset(getFontManager(), fontTrebuchetTexture2, getAssets(), "fonts/Trebuchet_MS_bold.ttf", 21, true, Color.rgb(255, 204, 82));

        mAllTextures.add(fontTrebuchetTexture);
        mAllTextures.add(fontTrebuchetTexture2);
        mAllTextureNames.add("font1");
        mAllTextureNames.add("font2");
        this.getFontManager().loadFont(this.fontTrebuchetBoldGold);
        this.getFontManager().loadFont(this.fontTrebuchetBoldGoldSmall);
    }


    private void init() {
        bgLayer = new Entity();
        scene.attachChild(bgLayer);


        levelMapImage = new Entity(0, 0, MAP_WIDTH, MAP_HEIGHT) {
            float lastX1
                    ,
                    lastX2
                    ,
                    lastX3
                    ,
                    lastY1
                    ,
                    lastY2
                    ,
                    lastY3;

            @Override
            public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                if (isPopupShown) return false;
                if (pSceneTouchEvent.getY() < MAP_BORDER_BOTTOM || pSceneTouchEvent.getY() > CAMERA_HEIGHT - MAP_BORDER_TOP) {
                    return false;
                }
                lastX3 = lastX2;
                lastX2 = lastX1;
                lastX1 = pTouchAreaLocalX;

                lastY3 = lastY2;
                lastY2 = lastY1;
                lastY1 = pTouchAreaLocalY;

                if (pSceneTouchEvent.getAction() == MotionEvent.ACTION_DOWN) {
                    dragInAction = true;
                    touchX = pTouchAreaLocalX;
                    touchY = pTouchAreaLocalY;
                } else if (pSceneTouchEvent.getAction() == MotionEvent.ACTION_UP) {
                    final float avgDeltaX = (lastX1 - lastX2);
                    final float avgDeltaY = (lastY1 - lastY2);
                    final Entity map = this;
                    this.registerEntityModifier(new DelayModifier(0.5f) {

                        @Override
                        protected void onManagedUpdate(float pSecondsElapsed, IEntity pEntity) {
                            float percentage = getSecondsElapsed() / getDuration();
                            float newX = getX() - avgDeltaX * (1 - percentage) / 2;
                            float newY = getY() - avgDeltaY * (1 - percentage) / 2;
                            if (newX <= 0 && newX + MAP_WIDTH >= CAMERA_WIDTH && newY <= MAP_BORDER_BOTTOM && newY + MAP_HEIGHT >= CAMERA_HEIGHT - MAP_BORDER_TOP) {
                                map.setX(newX);
                                map.setY(newY);
                            } else {
                                getEngine().runOnUpdateThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        map.clearEntityModifiers();
                                    }
                                });
                            }
                        }
                    });
                    dragInAction = false;
                } else if (pSceneTouchEvent.getAction() == MotionEvent.ACTION_MOVE) {

                    if (dragInAction) {
                        float newX = pSceneTouchEvent.getX() - touchX;
                        if (newX <= 0 && newX + MAP_WIDTH >= CAMERA_WIDTH) {
                            this.setX(newX);
                        }
                        //LOG.i("touch map " +pTouchAreaLocalX + "   " + pSceneTouchEvent.getY());
                        float newY = pSceneTouchEvent.getY() - touchY;
                        if (newY <= MAP_BORDER_BOTTOM && newY + MAP_HEIGHT >= CAMERA_HEIGHT - MAP_BORDER_TOP) {
                            this.setY(newY);
                        }
                    }
                }

                return false;
            }

        };
        levelMapImage.setAnchorCenter(0, 0);
        this.bgLayer.attachChild(levelMapImage);


        levelMapPart1 = new Sprite(0, 0, this.bgTextureRegion, getVertexBufferObjectManager());
        levelMapPart1.setAnchorCenter(0, 0);
        levelMapImage.attachChild(levelMapPart1);
        roadLayer = new Entity();
        //levelMapImage.attachChild(roadLayer);

        renderLevelAreas();
        scene.setTouchAreaBindingOnActionDownEnabled(true);
        scene.setTouchAreaBindingOnActionMoveEnabled(true);

        popupLayer = new Entity();
        bgLayer.attachChild(popupLayer);

        Sprite mapFrame = new Sprite(0, 0, frameTextureRegion, getVertexBufferObjectManager());
        mapFrame.setAnchorCenter(0, 0);
        bgLayer.attachChild(mapFrame);

        attachFameAndMoneyValues();
        revealEntityAndChildren(0.3f, 0, 1, bgLayer, null);
        scene.registerTouchArea(levelMapImage);

    }

    private void attachFameAndMoneyValues() {

        totalPointsTopText = new Text(CAMERA_WIDTH - 150, CAMERA_HEIGHT - 50, fontTrebuchetBoldGold, "" + GameProfile.getTotalAchievedPoints(mSQLiteHelper), getVertexBufferObjectManager());
        totalPointsTopText.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
        bgLayer.attachChild(totalPointsTopText);
        totalFameTopText = new Text(150, CAMERA_HEIGHT - 50, fontTrebuchetBoldGold, "" + GameProfile.getTotalFame(mSQLiteHelper), getVertexBufferObjectManager());
        totalFameTopText.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
        bgLayer.attachChild(totalFameTopText);
    }

    private void renderLevelAreas() {
        //this.levelHighlight = new Sprite(0, 0, arrowTextureRegion, getVertexBufferObjectManager());
        //levelHighlight.setAnchorCenter(0.5f, 0);
        int areaIndex = 0;
        for (final LevelAreaDef levelArea : LevelDefinition.getLevels()) {
            final int areaIndexFinal = areaIndex;
            int lastUnlockedAreaIndex = GameProfile.getLastUnlockedAreaIndex(mSQLiteHelper);
            if (isAreaCompleted(areaIndexFinal) || levelArea.getPreviousLevelAreaIndex() == null || isAreaCompleted(levelArea.getPreviousLevelAreaIndex())
                    || lastUnlockedAreaIndex + 1 >= areaIndexFinal) {
                if (lastUnlockedAreaIndex < areaIndexFinal) {
                    attachSetIcon(areaIndexFinal, false);
                } else {
                    attachSetIcon(areaIndexFinal, true);
                }
                attachFinishedLevelDots(areaIndexFinal);
            } else {
                attachSetIcon(areaIndexFinal, false);
            }
            areaIndex++;
        }
        //levelMapImage.attachChild(levelHighlight);
    }

    private void attachFinishedLevelDots(int areaIndex) {
        Map<Integer, Integer[]> finishedLevelsForArea = GameProfile.getAllFinishedLevelsForArea(areaIndex, mSQLiteHelper);
        int levelIndex = 0;
        List<Entity> iconVList = new LinkedList<Entity>();
        for (LevelDef level : LevelDefinition.getLevels()[areaIndex].getAreaLevels()) {
            boolean levelFinished = finishedLevelsForArea.keySet().contains(levelIndex);
            if (levelFinished) {
                Sprite levelFinishedDot = new Sprite(0, 0, levelCompleteDot, getVertexBufferObjectManager());
                float[] xy = finishedLevelDots.get(areaIndex + "_" + levelIndex);
                levelFinishedDot.setPosition(xy[0], xy[1]);
                levelMapImage.attachChild(levelFinishedDot);
            }
            levelIndex++;
        }
    }

    private void attachSetIcon(final int areaIndex, final boolean isUnlocked) {
        LevelAreaDef levelArea = LevelDefinition.getLevels()[areaIndex];
        ITextureRegion roadRegion = null;
        ITextureRegion areaIconRegion = null;
        if (isUnlocked) {
            areaIconRegion = setIconsAvailable.get(areaIndex);
            if (areaIndex > 0) {
                roadRegion = roadPartsOpened.get(areaIndex);
            }
        } else {
            areaIconRegion = setIconsLocked.get(areaIndex);
            if (areaIndex > 0) {
                roadRegion = roadPartsLocked.get(areaIndex);
            }
        }
        LOG.i("roadregion: " + roadRegion);
        final Entity levelAreaIcon = new Sprite(levelArea.getLevelMapCoords()[0], levelArea.getLevelMapCoords()[1], areaIconRegion, getVertexBufferObjectManager()) {
            float lastTouchDownX = -100;
            float lastTouchDownY = -100;

            public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                if (isPopupShown) return false;
                //Log.i("jewel", "touched " + pSceneTouchEvent.getAction());
                if (pSceneTouchEvent.getY() < MAP_BORDER_BOTTOM || pSceneTouchEvent.getY() > CAMERA_HEIGHT - MAP_BORDER_TOP) {
                    //Log.i("jewel", "touched levelhm");

                    return false;
                }
                if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN) {
                    //Log.i("jewel", "touched level1");
                    lastTouchDownX = pSceneTouchEvent.getX();
                    lastTouchDownY = pSceneTouchEvent.getY();
                    return false;
                } else if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
                    float upX = pSceneTouchEvent.getX();
                    float upY = pSceneTouchEvent.getY();
                    //Log.i("testtouch", lastTouchDownX + " " + lastTouchDownY + "   " + upX + " " + upY);
                    if (Math.abs(upX - lastTouchDownX) > 10 || Math.abs(upY - lastTouchDownY) > 10) {
                        return false; //level was dragged - does not recognize it as a level touch!
                    }
                    lastTouchDownY = -100;
                    lastTouchDownX = -100;
                    //Log.i("jewel", "touched level");
                    Entity thisEntity = areaList.get(areaIndex);
                    thisEntity.registerEntityModifier(new SequenceEntityModifier(
                            new ScaleAtModifier(0.1f, 1, 1.2f, 0.5f, 0.5f),
                            new ScaleAtModifier(0.1f, 1.2f, 1, 0.5f, 0.5f, new IEntityModifier.IEntityModifierListener() {
                                @Override
                                public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {
                                }

                                @Override
                                public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
                                    //levelHighlight.setPosition(levelArea.getLevelMapCoords()[0], levelArea.getLevelMapCoords()[1] + 20);
                                    //resetArrowAnimation();
                                    int lastUnlockedAreaIndex = GameProfile.getLastUnlockedAreaIndex(mSQLiteHelper);
                                    if (isUnlocked) {
                                        showLevelAreaPopup(areaIndex, null);
                                    } else {
                                        showUnlockAreaPopup(areaIndex);
                                    }
                                }
                            })
                    ));
                }
                return false;
            }
        };
        levelAreaIcon.setAnchorCenterY(0.45f);
        areaList.put(areaIndex, levelAreaIcon);
        if (roadRegion != null) {
            Sprite roadPart = new Sprite(0, 0, roadRegion, getVertexBufferObjectManager());
            roadPart.setAnchorCenter(0, 0);
            roadLayer.attachChild(roadPart);
            //FIXME
            roadPart.setAlpha(0);
            roadList.put(areaIndex, roadPart);
            /*
            if (!isUnlocked) {
                Sprite roadPartUnlocked = new Sprite(0, 0, roadPartsOpened.get(areaIndex), getVertexBufferObjectManager());
                roadPartUnlocked.setAnchorCenter(0,0);
                levelMapImage.attachChild(roadPartUnlocked);
                roadPartUnlocked.setAlpha(0f);
                roadList.put(0,roadPartUnlocked);
            }
            */
        }
        if (!isUnlocked) {
            int totalMoney = GameProfile.getTotalAchievedPoints(mSQLiteHelper);
            int totalFame = GameProfile.getTotalFame(mSQLiteHelper);
            boolean enoughMoney = levelArea.getCostMoneyToUnlock() <= totalMoney;
            boolean enoughFame = levelArea.getCostFameToUnlock() <= totalFame;
            if (enoughFame && enoughMoney) {
                final Entity emitterEntity = new Entity();
                levelAreaIcon.attachChild(emitterEntity);
                emitterEntity.registerEntityModifier(new LoopEntityModifier(new DelayModifier(0.2f + 0.1f * new Random().nextInt(5), new IEntityModifier.IEntityModifierListener() {
                    @Override
                    public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {
                        LOG.i("emittermod!");
                        new ParticleEmitter(1, 30, 0.6f + 0.1f * new Random().nextInt(5), levelAreaIcon.getWidth() / 2, 30, 0.7f, goldParticleRegion, getEngine(), emitterEntity).start();
                    }

                    @Override
                    public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
                    }
                })));
            }
        }
        levelMapImage.attachChild(levelAreaIcon);
        scene.registerTouchArea(levelAreaIcon);
        //Log.i("aldar", "Levelarea index: " + areaIndex + "  " + levelArea + "  " + levelArea.getPreviousLevelAreaIndex());
        if (areaToHighlightAtStart != null && areaIndex == areaToHighlightAtStart) {
            //center the map to the specified area
            float newX = CAMERA_WIDTH / 2 - levelArea.getLevelMapCoords()[0];
            if (newX > 0) {
                newX = 0;
            } else if (newX + MAP_WIDTH < CAMERA_WIDTH) {
                newX = CAMERA_WIDTH - MAP_WIDTH;
            }

            float newY = CAMERA_HEIGHT / 2 - MAP_BORDER_BOTTOM - levelArea.getLevelMapCoords()[1];


            if (newY > MAP_BORDER_BOTTOM) {
                newY = MAP_BORDER_BOTTOM;
            } else if (newY + MAP_HEIGHT < CAMERA_HEIGHT - MAP_BORDER_TOP) {
                newY = CAMERA_HEIGHT - MAP_BORDER_TOP - MAP_HEIGHT;
            }

            levelMapImage.setPosition(newX, newY);
            areaToHighlightAtStart = null;
            levelToHighlightAtStart = null;
        }

    }

    private void showUnlockAreaPopup(final int areaIndex) {
        scene.unregisterTouchArea(levelMapImage);
        isPopupShown = true;

        Sprite popupBg = getUnlockAreaBgSprite();
        popupBg.setAnchorCenter(0, 0);
        popupLayer.attachChild(popupBg);
        Sprite popupIllo = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 + 180, setPopupIllos.get(areaIndex), getVertexBufferObjectManager());
        popupLayer.attachChild(popupIllo);
        final Runnable closeButtonAction = new Runnable() {

            @Override
            public void run() {
                if (buttonUnlockArea != null) {
                    scene.unregisterTouchArea(buttonUnlockArea);
                }
                scene.unregisterTouchArea(closeButton);
                scene.registerTouchArea(levelMapImage);
                closeUnlockAreaPopup();
                backButtonAction = null;
            }
        };
        backButtonAction = closeButtonAction;
        closeButton = new CustomButtonSprite(
                CAMERA_WIDTH / 2 + 120, CAMERA_HEIGHT / 2 + 110, buttonClosedPressedTextureRegion.getTextureRegion(0),
                buttonClosedPressedTextureRegion.getTextureRegion(1),
                getVertexBufferObjectManager(),
                new CustomButtonSprite.OnClickListener() {
                    @Override
                    public void onClick(final CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                        revealEntityAndChildren(0.3f, 1, 0, popupLayer, closeButtonAction);
                    }
                }
        );

        closeButton.setPosition(CAMERA_WIDTH - 89, CAMERA_HEIGHT / 2 + 147);
        popupLayer.attachChild(closeButton);
        scene.registerTouchArea(closeButton);
        unlockPopupContent = constructUnlockPopupContent(areaIndex);
        popupLayer.attachChild(unlockPopupContent);
        revealEntityAndChildren(0.3f, 0, 1, popupLayer, null);


    }

    private Entity constructUnlockPopupContent(final int areaIndex) {
        Entity contentContainer = new Entity();
        LevelAreaDef area = LevelDefinition.getLevels()[areaIndex];
        int totalMoney = GameProfile.getTotalAchievedPoints(mSQLiteHelper);
        int totalFame = GameProfile.getTotalFame(mSQLiteHelper);
        boolean enoughMoney = area.getCostMoneyToUnlock() <= totalMoney;
        boolean enoughFame = area.getCostFameToUnlock() <= totalFame;

        //GREEN FAME and GREEN MONEY
        if (enoughMoney && enoughFame) {
            Entity requirements = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 + 60, areaReqGreenGreenRegion, getVertexBufferObjectManager());
            contentContainer.attachChild(requirements);
            buttonUnlockArea = new CustomButtonSprite(
                    CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 - 20, buttonUnlockTextureRegion.getTextureRegion(0), buttonUnlockTextureRegion.getTextureRegion(1),
                    getVertexBufferObjectManager(),
                    new CustomButtonSprite.OnClickListener() {
                        @Override
                        public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                            closeUnlockAreaPopup();
                            doUnlockArea(areaIndex, new Runnable() {
                                @Override
                                public void run() {
                                    scene.registerTouchArea(levelMapImage);
                                }
                            });
                        }
                    }
            );
            buttonUnlockArea.setEnabled(true);
            contentContainer.attachChild(buttonUnlockArea);
            scene.registerTouchArea(buttonUnlockArea);
        } else if (enoughFame) {
            Entity requirements = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 + 60, areaReqGreenRedRegion, getVertexBufferObjectManager());
            contentContainer.attachChild(requirements);
            Text warningText = new Text(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 - 15, fontTrebuchetBoldGoldSmall, "Not enough money\nto unlock this set", new TextOptions(HorizontalAlign.CENTER), getVertexBufferObjectManager());
            contentContainer.attachChild(warningText);
        } else if (enoughMoney) {
            Entity requirements = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 + 60, areaReqRedGreenRegion, getVertexBufferObjectManager());
            contentContainer.attachChild(requirements);
            Text warningText = new Text(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 - 15, fontTrebuchetBoldGoldSmall, "Not enough fame\nto unlock this set", new TextOptions(HorizontalAlign.CENTER), getVertexBufferObjectManager());
            contentContainer.attachChild(warningText);
        } else {
            Entity requirements = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 + 60, areaReqRedRedRegion, getVertexBufferObjectManager());
            contentContainer.attachChild(requirements);
            Text warningText = new Text(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 - 15, fontTrebuchetBoldGoldSmall, "Not enough fame & money\nto unlock this set", new TextOptions(HorizontalAlign.CENTER), getVertexBufferObjectManager());
            contentContainer.attachChild(warningText);
        }

        final Text totalMoneyText = new Text(CAMERA_WIDTH / 2 + 60, CAMERA_HEIGHT / 2 + 50, fontTrebuchetBoldGold, "" + area.getCostMoneyToUnlock(), getVertexBufferObjectManager());
        totalMoneyText.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
        contentContainer.attachChild(totalMoneyText);
        final Text totalFameText = new Text(CAMERA_WIDTH / 2 - 60, CAMERA_HEIGHT / 2 + 50, fontTrebuchetBoldGold, "" + area.getCostFameToUnlock(), getVertexBufferObjectManager());
        totalFameText.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
        contentContainer.attachChild(totalFameText);


        return contentContainer;
    }

    private void refreshMoneyAndFame() {
        totalPointsTopText.setText(GameProfile.getTotalAchievedPoints(mSQLiteHelper).toString());
        totalFameTopText.setText(GameProfile.getTotalFame(mSQLiteHelper).toString());
    }

    private void doUnlockArea(final Integer areaIndex, Runnable runAfterAreaUnlockedAction) {
        GameProfile.setLastUnlockedAreaIndex(areaIndex, mSQLiteHelper);
        GameProfile.setTotalAchievedPoints(GameProfile.getTotalAchievedPoints(mSQLiteHelper) - LevelDefinition.getLevels()[areaIndex].getCostMoneyToUnlock(), mSQLiteHelper);
        // not subtracting jewels any more
        // GameProfile.setTotalFame(GameProfile.getTotalFame(mSQLiteHelper) - LevelDefinition.getLevels()[areaIndex].getCostFameToUnlock(), mSQLiteHelper);

        refreshMoneyAndFame();

        final Entity areaIconLocked = areaList.get(areaIndex);
        final Entity roadLocked = roadList.get(areaIndex);
        //attach new unlocked area icon
        attachSetIcon(areaIndex, true);
        //retrieve new area icon
        Entity areaIconUnlocked = areaList.get(areaIndex);
        Entity roadOpen = roadList.get(areaIndex);
        roadOpen.setAnchorCenter(0, 0);
        roadList.put(areaIndex, roadOpen);
        //do cross fading
        float duration = 1f;
        fadeOutEntity(duration, areaIconLocked, new Runnable() {
            @Override
            public void run() {
                runOnUpdateThread(new Runnable() {
                    @Override
                    public void run() {
                        areaIconLocked.detachSelf();
                        scene.unregisterTouchArea(areaIconLocked);
                    }
                });
            }
        });
        revealEntity(duration, areaIconUnlocked, new Runnable() {
            @Override
            public void run() {
                runOnUpdateThread(new Runnable() {
                    @Override
                    public void run() {
                        showNextDiscoveredLockedArea(areaIndex + 1);
                    }
                });
            }
        });
        fadeOutEntity(duration, roadLocked, new Runnable() {
            @Override
            public void run() {
                runOnUpdateThread(new Runnable() {
                    @Override
                    public void run() {
                        roadLocked.detachSelf();
                    }
                });
            }
        });
        revealEntity(duration, roadOpen, new Runnable() {
            @Override
            public void run() {
            }
        });

        ParticleUtil.makeParticleCircle(1.5f,
                areaIconUnlocked.getX() - 10,
                areaIconUnlocked.getY() - 20,
                60,
                0.2f,
                1,
                20,
                goldParticleRegion,
                getEngine(),
                levelMapImage
        );


    }

    private void showNextDiscoveredLockedArea(int areaIndex) {
        if (areaIndex >= LevelDefinition.getLevels().length) {
            LOG.i("Last area unlocked, no new areas can be shown on the map");
            return;
        }
        attachSetIcon(areaIndex, false);
        Entity areaIcon = areaList.get(areaIndex);
        revealEntity(1f, areaIcon, new Runnable() {
            @Override
            public void run() {
                scene.registerTouchArea(levelMapImage);
            }
        });
        revealEntity(1f, roadList.get(areaIndex), null);
    }

    private void revealEntity(float duration, Entity entity, final Runnable afterAction) {
        changeEntityAlpha(duration, 0f, 1f, entity, afterAction);
    }

    private void fadeOutEntity(float duration, Entity entity, Runnable afterAction) {
        changeEntityAlpha(duration, 1f, 0f, entity, afterAction);
    }

    private void changeEntityAlpha(float duration, float fromAlpha, float toAlpha, Entity entity, final Runnable afterAction) {
        entity.registerEntityModifier(new AlphaModifier(duration, fromAlpha, toAlpha, new IEntityModifier.IEntityModifierListener() {
            @Override
            public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {
            }

            @Override
            public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
                if (afterAction != null) {
                    afterAction.run();
                }
            }
        }));

    }


    private void showLevelAreaPopup(Integer areaIndex, Integer levelToHighlight) {
        scene.unregisterTouchArea(levelMapImage);
        isPopupShown = true;
        Sprite popupBg = getChooseLevelBgSprite();
        popupBg.setAnchorCenter(0, 0);
        popupLayer.attachChild(popupBg);
        Sprite popupIllo = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 + 180, setPopupIllos.get(areaIndex), getVertexBufferObjectManager());
        popupLayer.attachChild(popupIllo);
        buttonStartGame = new CustomButtonSprite(
                CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 - 150, buttonPlayTextureRegion.getTextureRegion(0), buttonPlayTextureRegion.getTextureRegion(1), getVertexBufferObjectManager(),
                new CustomButtonSprite.OnClickListener() {
                    @Override
                    public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                        startLevel();
                    }
                }
        );
        buttonStartGame.setEnabled(false);
        popupBg.attachChild(buttonStartGame);
        scene.registerTouchArea(buttonStartGame);

        int startX = 100;
        Log.i("aldar", "arealevels: " + areaIndex + " " + LevelDefinition.getLevels()[areaIndex].getAreaLevels().size());
        Map<Integer, Integer[]> finishedLevelsForArea = GameProfile.getAllFinishedLevelsForArea(areaIndex, mSQLiteHelper);
        int levelIndex = 0;
        currentLevelIcons = new LinkedList<Entity>();
        levelHighlights = new LinkedList<Entity>();
        List<Entity> iconVList = new LinkedList<Entity>();
        for (LevelDef level : LevelDefinition.getLevels()[areaIndex].getAreaLevels()) {
            int[] levelPos = getLevelIconPosition(levelIndex);
            boolean levelFinished = finishedLevelsForArea.keySet().contains(levelIndex);
            boolean levelAvailable = levelFinished || finishedLevelsForArea.keySet().contains(levelIndex - 1) || levelIndex == 0;
            int maxFame = 5;
            int earnedFame = 0;
            if (levelFinished) {
                earnedFame = finishedLevelsForArea.get(levelIndex)[1];
            }
            final Entity levelIcon = getLevelIcon(areaIndex, levelIndex, levelFinished, levelAvailable, earnedFame, level.getMaxFame());
            levelIcon.setPosition(levelPos[0], levelPos[1]);
            /*if (levelFinished) {
                Entity levelIconV = new Sprite(0, 0, levelIconDoneV, getVertexBufferObjectManager());
                levelIconV.setPosition(levelIcon);
                iconVList.add(levelIconV);
            } */
            if (!GameProfile.isLevelAlreadyOpened(areaIndex, levelIndex, mSQLiteHelper) && levelAvailable) {
                levelIcon.registerEntityModifier(new LoopEntityModifier(
                        new DelayModifier(2.0f, new IEntityModifier.IEntityModifierListener() {
                            @Override
                            public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {
                                ParticleUtil.makeParticleCircle(3.0f,
                                        levelIcon.getX(),
                                        levelIcon.getY(),
                                        45,
                                        0.4f,
                                        1,
                                        20,
                                        blueParticleRegion,
                                        getEngine(),
                                        popupLayer
                                );
                            }

                            @Override
                            public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
                                //To change body of implemented methods use File | Settings | File Templates.
                            }
                        })
                ));
            }

            currentLevelIcons.add(levelIcon);

            popupLayer.attachChild(levelIcon);
            levelHighlights.add(getLevelHighlightFrame(levelIndex));
            popupLayer.attachChild(levelHighlights.get(levelIndex));
            levelHighlights.get(levelIndex).setVisible(false);
            scene.registerTouchArea(levelIcon);
            startX += 60;
            levelIndex++;
        }

        for (Entity e : iconVList) {
            popupLayer.attachChild(e);
        }

        //if specified levelToHighlight or unfinished levels in the area exist - pre-select level
        if (levelToHighlight != null || finishedLevelsForArea.size() < LevelDefinition.getLevels()[areaIndex].getAreaLevels().size()) {
            GameProfile.selectedLevelIndex = levelToHighlight != null ? levelToHighlight : finishedLevelsForArea.size();
            GameProfile.selectedLevelAreaIndex = areaIndex;
            Log.i("aldar", "highlight predefined level " + GameProfile.selectedLevelAreaIndex + " " + GameProfile.selectedLevelIndex + " fin levels size" + finishedLevelsForArea.size());
            levelHighlight = levelHighlights.get(GameProfile.selectedLevelIndex);
            levelHighlight.setPosition(getLevelIconPosition(GameProfile.selectedLevelIndex)[0], getLevelIconPosition(GameProfile.selectedLevelIndex)[1]);
            levelHighlight.setVisible(true);
            buttonStartGame.setEnabled(true);
        }
        final Runnable closeButtonAction = new Runnable() {
            @Override
            public void run() {
                closeChooseLevelPopup();
            }
        };

        backButtonAction = closeButtonAction;
        closeButton = new CustomButtonSprite(
                CAMERA_WIDTH / 2 + 152, CAMERA_HEIGHT / 2 + 145, buttonClosedPressedTextureRegion.getTextureRegion(0),
                buttonClosedPressedTextureRegion.getTextureRegion(1),
                getVertexBufferObjectManager(),
                new CustomButtonSprite.OnClickListener() {
                    @Override
                    public void onClick(final CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                        revealEntityAndChildren(0.3f, 1, 0, popupLayer, closeButtonAction);
                    }
                }
        );
        popupLayer.attachChild(closeButton);
        scene.registerTouchArea(closeButton);
        revealEntityAndChildren(0.3f, 0, 1, popupLayer, null);

    }


    private int[] getLevelIconPosition(int levelIndex) {
        int midX = CAMERA_WIDTH / 2;
        int topY = CAMERA_HEIGHT / 2 + 50;
        int botY = CAMERA_HEIGHT / 2 - 60;
        int difX = 110;
        if (levelIndex == 0) {
            return new int[]{midX - difX, topY};
        } else if (levelIndex == 1) {
            return new int[]{midX, topY};
        } else if (levelIndex == 2) {
            return new int[]{midX + difX, topY};
        } else if (levelIndex == 3) {
            return new int[]{midX - difX, botY};
        } else if (levelIndex == 4) {
            return new int[]{midX, botY};
        } else if (levelIndex == 5) {
            return new int[]{midX + difX, botY};
        }
        return null;
    }

    private void closeChooseLevelPopup() {
        isPopupShown = false;
        popupLayer.detachChildren();
        GameProfile.selectedLevelAreaIndex = null;
        GameProfile.selectedLevelIndex = null;
        buttonStartGame.setEnabled(false);
        scene.unregisterTouchArea(buttonStartGame);
        scene.unregisterTouchArea(closeButton);
        for (Entity e : getCurrentLevelIcons()) {
            scene.unregisterTouchArea(e);
        }
        scene.registerTouchArea(levelMapImage);
        backButtonAction = null;
    }

    private void closeUnlockAreaPopup() {
        if (buttonUnlockArea != null) {
            buttonUnlockArea.setEnabled(false);
            scene.unregisterTouchArea(buttonUnlockArea);
        }
        scene.unregisterTouchArea(closeButton);
        isPopupShown = false;
        popupLayer.detachChildren();
    }


    private boolean isAreaCompleted(int areaIndexFinal) {
        LevelAreaDef areaDef = LevelDefinition.getLevels()[areaIndexFinal];
        Map<Integer, Integer[]> finishedLevelsInArea = GameProfile.getAllFinishedLevelsForArea(areaIndexFinal, mSQLiteHelper);
        boolean allLevelsFinished = areaDef.getAreaLevels().size() == finishedLevelsInArea.size();
        return allLevelsFinished;
    }

    @Override
    public EngineOptions onMyCreateEngineOptions() {
        mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
        EngineOptions opts = new EngineOptions(true, ScreenOrientation.PORTRAIT_FIXED,//TODO replaced "PORTRAIT"
                new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), mCamera);
        opts.getAudioOptions().setNeedsSound(true);
        opts.getAudioOptions().setNeedsMusic(true);
        opts.getRenderOptions().setDithering(true);
        return opts;
    }

    @Override
    protected SQLiteHelper getSqLiteHelper() {
        return mSQLiteHelper;
    }


    private void startLevel() {
        GameProfile.setLevelAlreadyOpened(GameProfile.selectedLevelAreaIndex, GameProfile.selectedLevelIndex, mSQLiteHelper);
        Intent intent = new Intent();
        intent.setClass(this.getApplicationContext(), MainBoardScreen.class);
        startActivity(intent);
        this.finish();
    }

    @Override
    public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
        return false;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        LOG.i("keydown backbuttonaction = " + backButtonAction);
        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
            if (backButtonAction != null) {
                runOnUpdateThread(backButtonAction);
                LOG.i("keydown running action, now action = " + backButtonAction);
            } else {
                Intent intent = new Intent();
                intent.setClass(this.getApplicationContext(), StartMenuScreen.class);
                startActivity(intent);
                LevelMapScreen.this.finish();
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);    //To change body of overridden methods use File | Settings | File Templates.
    }

    private Sprite getChooseLevelBgSprite() {
        return new Sprite(0, 0, selectLevelPopupTextureRegion, getVertexBufferObjectManager());
    }

    private Sprite getUnlockAreaBgSprite() {
        return new Sprite(0, 0, unlockPopupTextureRegion, getVertexBufferObjectManager());
    }


    private Entity getLevelIcon(final int areaIndex, final int levelIndex, final boolean levelFinished, final boolean levelAvailable, int earnedFame, int maxFame) {
        final Entity levelIcon = new Rectangle(0, 0, 75, 65, getVertexBufferObjectManager()) {
            @Override
            public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                Log.i("leveltouch", "touched!!! " + areaIndex + " " + levelIndex);
                if (pSceneTouchEvent.isActionDown()) {
                    Log.i("leveltouch", "touched!!! " + areaIndex + " " + levelIndex);
                    if (levelAvailable) {
                        Log.i("leveltouch", "available!!! " + areaIndex + " " + levelIndex);
                        if (levelHighlight != null) {
                            //hide previously highlighted level
                            levelHighlight.setVisible(false);
                        }
                        levelHighlight = levelHighlights.get(levelIndex);
                        levelHighlight.setVisible(true);
                        levelHighlight.setPosition(getLevelIconPosition(levelIndex)[0], getLevelIconPosition(levelIndex)[1]);
                        buttonStartGame.setEnabled(true);
                        GameProfile.selectedLevelAreaIndex = areaIndex;
                        GameProfile.selectedLevelIndex = levelIndex;
                    }
                }
                return true;
            }
        };
        if (levelFinished) {
            Entity levelFinishedIcon = getLevelFinishedIcon(earnedFame);
            levelIcon.attachChild(levelFinishedIcon);
            levelFinishedIcon.setPosition(levelIcon.getWidth() / 2, levelIcon.getHeight() / 2);
        } else if (!levelAvailable) {
            Entity levelLockedIcon = getLevelLockedIcon();
            levelIcon.attachChild(levelLockedIcon);
            levelLockedIcon.setPosition(levelIcon.getWidth() / 2, levelIcon.getHeight() / 2);
        } else {
            Entity levelReadyIcon = getLevelReadyIcon();
            levelIcon.attachChild(levelReadyIcon);
            levelReadyIcon.setPosition(levelIcon.getWidth() / 2, levelIcon.getHeight() / 2);
        }
        if (levelAvailable) {
            Entity levelNumber = new Sprite(0, 0, levelNumbers.getTextureRegion(levelIndex), getVertexBufferObjectManager());
            levelIcon.attachChild(levelNumber);
            levelNumber.setPosition(levelIcon.getWidth() / 2, levelIcon.getHeight() / 2);
        }
        return levelIcon;
    }

    private Entity getLevelHighlightFrame(int levelIndex) {
        Entity levelHighlight = new Entity();
        levelHighlight.attachChild(new Sprite(0, 0, levelSelectedFrame, getVertexBufferObjectManager()));
        levelHighlight.attachChild(new Sprite(0, 0, levelNumbers.getTextureRegion(6 + levelIndex), getVertexBufferObjectManager()));
        return levelHighlight;
    }

    private Entity getLevelFinishedIcon(int jewels) {
        return new Sprite(0, 0, levelIconJewels.getTextureRegion(jewels + 2), getVertexBufferObjectManager());
    }

    private Entity getLevelLockedIcon() {
        return new Sprite(0, 0, levelIconJewels.getTextureRegion(0), getVertexBufferObjectManager());
    }

    private Entity getLevelReadyIcon() {
        return new Sprite(0, 0, levelIconJewels.getTextureRegion(1), getVertexBufferObjectManager());
    }

    private Entity getSingleFameIcon(boolean gold) {
        if (gold) {
            return new Sprite(0, 0, fameGoldIconRegion, getVertexBufferObjectManager());
        } else {
            return new Sprite(0, 0, fameEmptyIconRegion, getVertexBufferObjectManager());
        }
    }

    public List<Entity> getCurrentLevelIcons() {
        return currentLevelIcons;
    }

    private ITiledTextureRegion loadTiled(String filename, int w, int h, int col, int row, Context context) {
        BitmapTextureAtlas texture = new BitmapTextureAtlas(getTextureManager(), w, h, TextureOptions.BILINEAR);
        ITiledTextureRegion region = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(texture, context, filename, 0, 0, col, row);
        texture.load();
        return region;
    }

    private ITextureRegion load(String filename, int w, int h, Context context, boolean toLoad) {
        BitmapTextureAtlas texture = new BitmapTextureAtlas(getTextureManager(), w, h, TextureOptions.BILINEAR);
        ITextureRegion region = BitmapTextureAtlasTextureRegionFactory.createFromAsset(texture, context, filename, 0, 0);
        //texture.load();
        if (toLoad) {
            mAllTextures.add(texture);
            mAllTextureNames.add(filename);
        }
        return region;
    }

    private ITextureRegion load(String filename, int w, int h, Context context) {
        return load(filename, w, h, context, true);
    }

    static {
        finishedLevelDots.put("0_0", new float[]{245, 184});
        finishedLevelDots.put("0_1", new float[]{257, 202});
        finishedLevelDots.put("0_2", new float[]{265, 223});
        finishedLevelDots.put("0_3", new float[]{272, 245});
        finishedLevelDots.put("0_4", new float[]{280, 266});
        finishedLevelDots.put("0_5", new float[]{289, 286});

        finishedLevelDots.put("1_0", new float[]{255, 344});
        finishedLevelDots.put("1_1", new float[]{234, 350});
        finishedLevelDots.put("1_2", new float[]{214, 358});
        finishedLevelDots.put("1_3", new float[]{195, 369});
        finishedLevelDots.put("1_4", new float[]{179, 385});
        finishedLevelDots.put("1_5", new float[]{166, 400});

        finishedLevelDots.put("2_0", new float[]{188, 514});
        finishedLevelDots.put("2_1", new float[]{206, 530});
        finishedLevelDots.put("2_2", new float[]{222, 547});
        finishedLevelDots.put("2_3", new float[]{235, 564});
        finishedLevelDots.put("2_4", new float[]{246, 583});
        finishedLevelDots.put("2_5", new float[]{256, 603});

        finishedLevelDots.put("3_0", new float[]{228, 752});
        finishedLevelDots.put("3_1", new float[]{217, 774});
        finishedLevelDots.put("3_2", new float[]{208, 796});
        finishedLevelDots.put("3_3", new float[]{200, 819});
        finishedLevelDots.put("3_4", new float[]{194, 843});
        finishedLevelDots.put("3_5", new float[]{188, 867});

        finishedLevelDots.put("4_0", new float[]{220, 981});
        finishedLevelDots.put("4_1", new float[]{240, 996});
        finishedLevelDots.put("4_2", new float[]{258, 1011});
        finishedLevelDots.put("4_3", new float[]{276, 1028});
        finishedLevelDots.put("4_4", new float[]{292, 1046});
        finishedLevelDots.put("4_5", new float[]{306, 1066});

        finishedLevelDots.put("5_0", new float[]{350, 1216});
        finishedLevelDots.put("5_1", new float[]{348, 1242});
        finishedLevelDots.put("5_2", new float[]{344, 1267});
        finishedLevelDots.put("5_3", new float[]{339, 1293});
        finishedLevelDots.put("5_4", new float[]{332, 1318});
        finishedLevelDots.put("5_5", new float[]{321, 1343});

        finishedLevelDots.put("6_0", new float[]{248, 1479});
        finishedLevelDots.put("6_1", new float[]{237, 1502});
        finishedLevelDots.put("6_2", new float[]{230, 1525});
        finishedLevelDots.put("6_3", new float[]{233, 1548});
        finishedLevelDots.put("6_4", new float[]{247, 1568});
        finishedLevelDots.put("6_5", new float[]{264, 1585});

        finishedLevelDots.put("7_0", new float[]{245, 1711});
        finishedLevelDots.put("7_1", new float[]{224, 1717});
        finishedLevelDots.put("7_2", new float[]{203, 1727});
        finishedLevelDots.put("7_3", new float[]{184, 1743});
        finishedLevelDots.put("7_4", new float[]{175, 1766});
        finishedLevelDots.put("7_5", new float[]{175, 1790});

    }

}
